import { ArchetypeMaskUtil } from "./Archetype";
import { Component } from "./Component";

/**
 * trait是entity的一个切片,定义了entity的其中一部分
 */

export class TraitProperty {
    typeMask: bigint = 0n;
    propName: string = '';
}

export class Trait {
    private _mask: bigint = 0n;
    private _classId: number = 0;
    private _propertyMap = new Map<bigint, TraitProperty>();

    private static nextClassId = 1;

    constructor() {
        this._classId = Trait.nextClassId++;
    }

    get mask() {
        return this._mask;
    }

    addProperty(prop: TraitProperty) {
        if (this._propertyMap.has(prop.typeMask)) {
            throw new Error(`Trait ${this.constructor.name} property ${prop.propName} already added`);
        }

        this._propertyMap.set(prop.typeMask, prop);

        // 更新mask
        this._mask = ArchetypeMaskUtil.add(this._mask, prop.typeMask);
    }

    forEachProperty(callback: (prop:TraitProperty) => void) {
        this._propertyMap.forEach((value)=>{
            callback(value);
        });
    }

    static getData(traitClass: any):Trait {
        return traitClass.__tt;
    }

    static getStockBundle<T>(traitClass: {prototype: T}):T {
        return (traitClass as any).__sb as T;
    }
}

// export class ComponentBundle<T> {
//     private _trait: Trait;
//     private _components: Component[] = [];

//     get trait() {
//         return this._trait;
//     }

//     get components() {
//         return this._components;
//     }
// }

export function ecs_trait_property(type: typeof Component) {
    return function (target: any, name: string) {
        // 如果target.constructor.___trait_bundle不存在，则创建一个
        // if (!target.constructor.___trait_bundle) {
        //     target.constructor.___trait_bundle = new ComponentBundle();
        // }

        // TraitRegistry.register(target);
        const trait = target.constructor.__tt || (target.constructor.__tt = new Trait());

        const prop = new TraitProperty();
        prop.typeMask = Component.getMask(type);
        prop.propName = name;

        trait.addProperty(prop);
    }
}

export function ecs_trait() {
    return function (target: any) {
        if (!target.__sb) {
            target.__sb = new target();
        }
    }
}
